package cn.wolfcode.car.business.service.impl;


import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class ServiceItemServiceImpl implements IServiceItemService {

    @Autowired
    private ServiceItemMapper serviceItemMapper;

    @Autowired
    private ICarPackageAuditService carPackageAuditService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private IBpmnInfoService bpmnInfoService;


    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        return new TablePageInfo<ServiceItem>(serviceItemMapper.selectForList(qo));
    }


    @Override
    public void save(ServiceItem serviceItem) {
        //因为页面仅仅手机部分服务单项信息，而忽略很多默认状态操作(比如创建时间， 审核状态，上下架)
        //如果直接进行insert操作， 发现很多列数据是没有或者不合法的
        //此时需要进行额外补齐
        serviceItem.setCreateTime(new Date());
        //审核状态
        if(serviceItem.getCarPackage() == ServiceItem.CARPACKAGE_YES){
            //如果是套餐需要进行审核
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }else{
            //非套餐， 无需审核
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }
        //建议进行手动设置
        //开发建议：重要属性自己去控制
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);

        serviceItemMapper.insert(serviceItem);
    }

    @Override
    public ServiceItem get(Long id) {
        return serviceItemMapper.selectByPrimaryKey(id);
    }


    @Override
    public void update(ServiceItem serviceItem) {
        //当数据进行更新时， 如果页面收集的数据是部分数据， 此时更新操作需要考虑数据丢失问题
        //此时怎么办？
        //方案1：在update sql中将没有更新字段删除
        //方案2：先查， 替换，更新
        //通过id作为条件查询数据，将需要修改数据替换，更新
        //方案3：在mybatis sql中使用动态sql   <if> + <set>

        //存问题：业务要求，在审核中的数据是不允许修改，上架的数据不允许修改
        //此时该怎么办
        //更新前， 先进行状态判断
        ServiceItem temp = this.get(serviceItem.getId());
        //temp.getAuditStatus() == ServiceItem.AUDITSTATUS_AUDITING
        //equals比较是interge类型内容， 如使用== 可能存在比较内存地址隐患
        if(ServiceItem.AUDITSTATUS_AUDITING.equals(temp.getAuditStatus())){
            throw new BusinessException("服务项目正在审核中,不可修改");
        }else if(ServiceItem.SALESTATUS_ON.equals(temp.getSaleStatus())){
            throw new BusinessException("上架服务项目不能修改，请下架后再修改");
        }
        serviceItemMapper.updateByPrimaryKey(serviceItem);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            serviceItemMapper.deleteByPrimaryKey(dictId);
        }
    }

    @Override
    public List<ServiceItem> list() {
        return serviceItemMapper.selectAll();
    }

    @Override
    public void saleOn(Long id) {
        //拓展： 如果是套餐，必须审核通过， 如果不是套餐
        //将是否上架状态改为 上架状态
        serviceItemMapper.changeSaleStatus(id, ServiceItem.SALESTATUS_ON);
    }

    @Override
    public void saleOff(Long id) {
        //  2：如果是套餐，将审核状态修改为初始化，只有审核通过之后才可以上架
        serviceItemMapper.changeSaleStatus(id, ServiceItem.SALESTATUS_OFF);
    }

    @Override
    public void startAudit(Long id, Long bpmnInfoId, Long director, Long finance, String info) {
        //判断审核满足条件
        ServiceItem serviceItem = this.get(id);
        if(serviceItem == null || ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())
            || !ServiceItem.AUDITSTATUS_INIT.equals(serviceItem.getAuditStatus())){
            throw  new BusinessException("参数不合法");
        }
        //服务单项状态-审核中
        serviceItemMapper.changeAuditStatus(id, ServiceItem.AUDITSTATUS_AUDITING);
        //套餐审核记录信息-业务线
        CarPackageAudit audit = new CarPackageAudit();
        audit.setServiceItemId(id);
        audit.setServiceItemInfo(serviceItem.getInfo());
        audit.setServiceItemPrice(serviceItem.getDiscountPrice());
        audit.setCreator(ShiroUtils.getUser().getUserName());  //创建者
        audit.setCreateTime(new Date());
        //当前节点审核人
        audit.setAuditorId(director);  //如果店长为null 结束流程
        audit.setBpmnInfoId(bpmnInfoId);
        audit.setInfo(info);
        audit.setStatus(CarPackageAudit.STATUS_IN_ROGRESS);
        carPackageAuditService.save(audit);

        //启动流程-流程线
        //使用businessKey 将业务线与流程线绑定
        String businessKey = audit.getId().toString();
        BpmnInfo bpmnInfo = bpmnInfoService.get(bpmnInfoId);
        Map<String, Object> map = new HashMap<>();
        //activit7操作时判断不支持 BigDecimal
        map.put("discountPrice", serviceItem.getDiscountPrice().longValue());
        if(director != null){
            map.put("director", director);
        }
        if(finance != null){
            map.put("finance", finance);
        }
        //此处暂时不设置审核状态的变量值， 在最后做审核操作时，才明确指定具体变量值

        //1:启动key  2:流程图中各种参设置  3:businessKey
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey
                (bpmnInfo.getActProcessKey(), businessKey, map);

        //流程实例id
        carPackageAuditService.updateInstanceId(audit.getId(), processInstance.getId());

    }

    @Override
    public void changeAuditStatus(Long id, Integer status) {
        serviceItemMapper.changeAuditStatus(id, status);
    }
}
